/*
 * Complex.cpp
 *
 *  Created on: Apr 20, 2013
 *      Author: mvrocha
 */

#include "Complex.h"

namespace math
{

Complex::Complex()
{
	this->imag = 0;
	this->real = 0;
}

Complex::Complex(double a)
{
	this->imag = 0;
	this->real = a;
}

Complex::Complex(double a, double b)
{
	this->imag = b;
	this->real = a;
}

double Complex::getReal()
{
	return this->real;
}

double Complex::getImag()
{
	return this->imag;
}

double Complex::getPhase()
{
	if (this->real == 0)
		return (this->imag > 0 ? PI / 2 : -PI / 2);

	return atan2(this->imag, this->real);
}

double Complex::getModule()
{
	return sqrt(this->imag * this->imag + this->real * this->real);
}

double Complex::getReal() const
{
	return this->real;
}
double Complex::getImag() const
{

	return this->imag;
}

double Complex::getPhase() const
{
	if (this->real == 0)
		return (this->imag > 0 ? PI / 2 : -PI / 2);

	return atan2(this->imag, this->real);
}

double Complex::getModule() const
{
	return sqrt(this->imag * this->imag + this->real * this->real);
}

const Complex Complex::operator+=(const Complex& _x)
{
	this->real += _x.getReal();
	this->imag += _x.getImag();
	return *this;
}

const Complex Complex::operator-=(const Complex& _x)
{
	this->real -= _x.getReal();
	this->imag -= _x.getImag();
	return *this;
}

const Complex Complex::operator*=(const Complex& _x)
{
	Complex aux = *this;

	this->real = (aux.getReal() * _x.getReal() - aux.getImag() * _x.getImag());
	this->imag = (aux.getReal() * _x.getImag() + aux.getImag() * _x.getReal());

	return *this;
}

const Complex Complex::operator/=(const Complex& _x)
{
	Complex aux = *this;
	double div = _x.getModule() * _x.getModule();

	this->real = (aux.getReal() * _x.getReal() + aux.getImag() * _x.getImag())
			/ div;
	this->imag = (aux.getReal() * _x.getImag() - aux.getImag() * _x.getReal())
			/ div;

	return *this;
}

Complex Complex::operator+(const Complex& _x)
{
	Complex ret = *this;
	ret += _x;
	return ret;
}

Complex Complex::operator-(const Complex& _x)
{
	Complex ret = *this;
	ret -= _x;
	return ret;
}

Complex Complex::operator*(const Complex& _x)
{
	Complex ret = *this;
	ret *= _x;
	return ret;
}

Complex Complex::operator/(const Complex& _x)
{
	Complex ret = *this;
	ret /= _x;
	return ret;
}

Complex Complex::operator~()
{
	return Complex(this->real, -this->imag);
}

Complex Complex::operator^(const double& _x)
{
	double phase, mod;
	mod = std::pow(this->getModule(), _x);
	phase = this->getPhase() * _x;
	Complex ret(mod * std::cos(phase), mod * std::sin(phase));
	return ret;
}

bool Complex::operator==(const Complex& _x)
{
	if (this->imag - _x.getImag() < EPSILON && this->real - _x.getReal()
			< EPSILON)
		return true;
	return false;
}
bool Complex::operator!=(const Complex& _x)
{
	if (this->imag - _x.getImag() < EPSILON && this->real - _x.getReal()
			< EPSILON)
		return false;
	return true;
}

std::ostream& operator<<(std::ostream& os, const math::Complex& c)
{
	if (c.getImag() != 0 && c.getReal() != 0)
		os << "(" << c.getReal() << ")+j(" << c.getImag() << ")";
	else if (c.getImag() != 0)
		os << "j(" << c.getImag() << ")";
	else
		os << c.getReal();

	return os;
}
} /* namespace math */
